home *** CD-ROM | disk | FTP | other *** search
- /*
- File: UnitTableFunctions.c
-
- Contains: This contains the function entry points for each function
- code passed to DoDriverIO.
-
- Version: 1.0
-
- Copyright: © 1998-2000 by Apple Computer, Inc., all rights reserved.
-
-
- */
-
- #include <Disks.h>
- #include <DriverGestalt.h>
- #include <Gestalt.h>
- #include <NameRegistry.h>
- #include <Power.h>
- #include <Resources.h>
- #include <Strings.h>
- #include <Devices.h>
-
- // Unit Table Driver specifc headers
- #include "UnitTableDoDriverIO.h"
- #include "UnitTableFunctions.h"
- #include "UnitTableDriveQSupport.h"
- #include "UnitTableFloppySupport.h"
- #include "UnitTablePCExchangeSupport.h"
- #include "UnitTableReadWriteSupport.h"
- #include "UnitTableDriverIcons.h"
- #include "UnitTableDeviceAccess.h"
- #include "UnitTableCWDefines.h"
-
- typedef struct DriveRequestPB
- {
- volatile ParmBlkPtr theIOPB;
- IOCommandID ioCommandID;
- volatile OSStatus status;
- UInt8 currentExecutionState;
- } DriveRequestPB, *DriveRequestPBPtr;
-
- typedef struct DriverGlobalsStructure
- {
- DriveRequestPB drivePB;
- DriveRequestPB ejectPB; // Use this so that t
- DriverRefNum drvrRefNum; // Our driver reference number
- RegEntryID drvrRegEntryID;
- } DriverGlobalsStructure;
-
- // The values for the states of the state machines
- enum
- {
- // Mount State Machine
- kMountStartState = 1,
- kMountPreventRemovalState,
- kMountInstallDriveState,
-
- // Eject State Machine
- kEjectStartState,
- kEjectAllowRemovalDone,
- kEjectCartridgeDone
- };
-
- // These supporting functions are in this file…
- static void StandardControlCallCompletion(UInt32 userData, OSStatus status );
- static void ReadWriteFinishCommand ( UInt32 userData, OSStatus status );
- static void InitializeDriveAccessDone(UInt32 userData, OSStatus status );
-
- static OSStatus SetMountInterruptTimer( void );
- static OSStatus ClearMountInterruptTimer( void );
- static OSStatus MountSecondaryInterrupt( void *p1, void *p2);
-
- static void MountTheCartridge( UInt32 userData, OSStatus status );
- static void DriveInstallCompletion(Boolean wasSuccessful);
- static void EjectTheCartridge( UInt32 userData, OSStatus status );
-
- //----------------------------------------------------------------------------------
- // Globals
- //----------------------------------------------------------------------------------
- static MediaIconStruct gDriveIcon; // static structure for control calls
- static TimerID gInterruptTimer = 0;
- static DriverGlobalsStructure gTheDriverGlobals;
-
- //----------------------------------------------------------------------------------
- // Driver calls
- //----------------------------------------------------------------------------------
-
- // Always run at task level, can allocate and move memory.
- OSStatus DriverInitializeCmd ( DriverRefNum theRefNum, RegEntryIDPtr theRegEntryPtr )
- {
- OSStatus err = noErr;
-
- gTheDriverGlobals.drvrRefNum = theRefNum; // Our driver reference number
-
- if ( theRegEntryPtr != nil )
- {
- RegistryEntryIDCopy( theRegEntryPtr, &gTheDriverGlobals.drvrRegEntryID ); // Our driver Reg Entry ID Ptr
- }
- else
- {
- // No RegEntryID was passed in
- RegistryEntryIDInit( &gTheDriverGlobals.drvrRegEntryID );
- }
-
- return (err);
- }
-
- // Always run at task level, can allocate and move memory.
- OSStatus DriverFinalizeCmd ( DriverRefNum theRefNum, RegEntryIDPtr theRegEntryPtr )
- {
- #pragma unused ( theRefNum, theRegEntryPtr )
- OSStatus err = noErr;
-
- return (err);
- }
-
- // Always run at task level, can allocate and move memory.
- OSStatus DriverSupersededCmd ( DriverRefNum theRefNum, RegEntryIDPtr theRegEntryPtr )
- {
- #pragma unused ( theRefNum, theRegEntryPtr )
-
- OSErr err = noErr;
-
- return (err);
- }
-
- // Always run at task level, can allocate and move memory.
- OSStatus DriverReplaceCmd ( DriverRefNum theRefNum, RegEntryIDPtr theRegEntryPtr )
- {
- #pragma unused ( theRefNum, theRegEntryPtr )
- OSStatus err = noErr;
-
- return (err);
- }
-
- // Always run at task level, can allocate and move memory.
- OSStatus DriverOpenCmd (ParmBlkPtr pb)
- {
- #pragma unused (pb)
- OSStatus err = noErr;
-
- err = InitializeDeviceAccess( gTheDriverGlobals.drvrRefNum, &gTheDriverGlobals.drvrRegEntryID );
-
- if( err == noErr )
- {
- gTheDriverGlobals.drivePB.theIOPB = nil;
- gTheDriverGlobals.drivePB.currentExecutionState = kMountStartState;
-
- // Set up our color icon family
- BuildMediaIconFamily();
-
- // Let the world know we can do DriverGestalt calls
- DriverGestaltOn(gTheDriverGlobals.drvrRefNum);
-
- if( IsDeviceAccessEnabled() == false )
- {
- return noErr;
- }
-
- err = InstallDriveQueueElement( gTheDriverGlobals.drvrRefNum );
-
- // See if we can mount the media
- err = MountSecondaryInterrupt( nil, nil );
- }
-
- return(err);
- }
-
- // Always run at task level, can allocate and move memory.
- OSStatus DriverCloseCmd (ParmBlkPtr pb)
- {
- #pragma unused (pb)
- OSStatus err = noErr;
-
- // If an interrupt timer is set, cancel it!
- ClearMountInterruptTimer();
-
- // If a command is pending, wait for it to finish. Since the close
- // call is made at Task Time, this polling will not cause a deadlock.
- while( gTheDriverGlobals.drivePB.theIOPB != nil )
- {
- // Do Nothing till the command is done
- }
-
- // Let the world know we can no longer do DriverGestalt calls
- DriverGestaltOff(gTheDriverGlobals.drvrRefNum);
-
- // Dequeue all drive volumes
- RemoveDriveQueueElement();
-
- // tell the DAM to terminate
- err = TerminateDeviceAccess( gTheDriverGlobals.drvrRefNum, &gTheDriverGlobals.drvrRegEntryID );
-
- DestroyMediaIconFamily();
-
- return (err);
- }
-
- // May run at interrupt level, CANNOT allocate or move memory.
- OSStatus DriverControlCmd ( IOCommandID ioCommandID, ParmBlkPtr pb )
- {
- OSStatus err = noErr;
- CntrlParamPtr pbPtr;
- SInt16 driveNum;
-
- pbPtr = (CntrlParamPtr) pb;
- driveNum = pbPtr->ioVRefNum;
-
- // Parse the control codes…
- switch(pbPtr->csCode)
- {
- case killCode:
- {
- // The Device Manager will convert this control code to the
- // equivalent function code and call DoDriverIO
- err = controlErr;
- }
- break;
-
- case kVerify:
- {
- // Verify the media, Currently, only done for floppy disks.
- if( IsDriveAFloppy( driveNum ) == true )
- {
- // Since this call does not complete immediatley for floppy disks,
- // set up the information so that the StandardControlCallCompletion
- // routine can finish the IO when called.
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.theIOPB = nil;
- gTheDriverGlobals.drivePB.ioCommandID = ioCommandID;
- err = FloppyControlCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, &StandardControlCallCompletion );
- }
- else if( IsDriveNumberValid( driveNum ) == true )
- {
- // For non-floppy disks, report noErr to make the system
- // think that the driver formatted the media. This may
- // need to be changed to be drive dependent if there is
- // a device that the driver supports that has no low-level
- // format already on the media.
- err = noErr;
- }
- else
- {
- // The requested drive doesn't belong to this driver,
- // return a no such drive error.
- err = nsDrvErr;
- }
- }
- break;
-
- case kFormat:
- {
- // Format the media. Currently, only done for floppy disks.
- if( AreThereMountedDrives() == false )
- {
- // The requested drive doesn't have media inserted,
- // return a no such drive error.
- err = nsDrvErr;
- break;
- }
-
- if ( IsDriveNumWriteProtected(driveNum) == true )
- {
- // The media is write protected, return a write protect error.
- err = wPrErr;
- break;
- }
-
- if( IsDriveAFloppy( driveNum ) == true )
- {
- // Since this call does not complete immediately for floppy disks,
- // set up the information so that the StandardControlCallCompletion
- // routine can finish the IO when called.
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.theIOPB = nil;
- gTheDriverGlobals.drivePB.ioCommandID = ioCommandID;
- err = FloppyControlCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, &StandardControlCallCompletion );
- }
- else if( IsDriveNumberValid( driveNum ) == true )
- {
- // For non-floppy disks, report noErr to make the system
- // think that the driver formatted the media. This may
- // need to be changed to be drive dependent if there is
- // a device that the driver supports that has no low-level
- // format already on the media.
- err = noErr;
- }
- else
- {
- // The requested drive doesn't belong to this driver,
- // return a no such drive error.
- err = nsDrvErr;
- }
- }
- break;
-
- case kEject:
- {
- // We get this call whenever a volume is put away (dragged to trash).
- if ( IsDriveNumberValid( driveNum ) == false )
- {
- // If we did not find a drive and volume, report drive not found error.
- err = nsDrvErr;
- break;
- }
-
- // This is probably not needed because there could be media in the drive without
- // having a partition marked as mounted.
- /* if( AreThereMountedDrives() == false )*/
- /* {*/
- /* err = nsDrvErr; // no Media is inserted, return an error*/
- /* break;*/
- /* }*/
-
- EjectDriveNum( driveNum );
-
- if ( AreThereMountedDrives() == false ) // If no more mounted volumes…
- {
- // Since this call does not complete immediately, set up the information
- // so that the StandardControlCallCompletion routine can finish the IO when called.
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.currentExecutionState = kEjectStartState;
- EjectTheCartridge( (UInt32)&gTheDriverGlobals, noErr );
- err = noErr;
- }
- }
- break;
-
- case kDriveIcon: // Return icon displayed during media initialization
- case kMediaIcon: // Return icon displayed on desktop for media
- {
- if( AreThereMountedDrives() == false )
- {
- err = nsDrvErr; // no Media is inserted, return an error
- break;
- }
- else
- {
- if ( IsDriveNumberValid( driveNum ) == false ) // Check if drive number is invalid
- {
- err = nsDrvErr; // report drive not found error
- break;
- }
-
- GetMediaIconForDriveNum( driveNum, (DiskIcon *) &gDriveIcon.mediaIcon);
-
- // Copy over the DriveInfo string from the global param block
- PStrCopy(gDriveIcon.mediaWhereString, GetDeviceWhereString() );
-
- // Finally, return the pointer to the icon in csParam
- *(MediaIconStruct**)pbPtr->csParam = &gDriveIcon;
-
- err = noErr; // clear any error from above
- }
- }
- break;
-
- case kDriveInfo:
- {
- pbPtr->csParam[0] = 0; // Upper Word is always 0;
- pbPtr->csParam[1] = 0; // Clear Lower Word
-
- if( IsDriveAFloppy( driveNum ) == true )
- {
- err = FloppyControlCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, &StandardControlCallCompletion );
- }
- else if( IsDriveNumberValid( driveNum ) == true )
- {
- // If we currently have a LS-120 loaded, return the following info
- pbPtr->csParam[1] = ( 1 << 11 ) // Drive cardinality (0 - primary, 1 - secondary)
- | ( 0 << 10 ) // Media removability ( 0 - removable, 1 - fixed )
- | ( 1 << 9 ) // Interface ( 0 - floppy, 1 - SCSI )
- | ( 1 << 8 ) // Location ( 0 - internal, 1 - external )
- // Bits 4,5,6,7 are reserved
- | 1; // Drive Type ( use 1 for Unknown drive (Not a floppy) )
- }
- else
- {
- err = nsDrvErr; // requested drive doesn't belong to this driver
- }
- }
- break;
-
-
- case kDriverConfigureCode:
- {
- DriverConfigParam *configPtr; // local pointer to drive config structure
-
- configPtr = (DriverConfigParam *) pbPtr;
- switch(configPtr->driverConfigureSelector)
- {
- case kdgFlush:
- {
- // Issue a Flush cache Command to the drive
- //err = FlushDriveWriteCache(&gTheDriverGlobals.drivePB.executePB, nil);
- err = noErr;
- }
- break;
-
- default:
- {
- err = controlErr;
- }
- break;
- }
- }
- break;
-
- case kcsSetBootPartitionCode: // Set Startup Partition
- {
- // If the media is partitioned, this should update the boot partition
- // status information in the partition map on the drive.
- err = noErr;
- }
- break;
-
- #if 0
- case kcsMountVolume: // Mount Volume
- {
- // Who uses this call, and what exactly is its purpose?
- if (!vol->hasPMapEntry) // volume must have a partition map entry on media
- err = controlErr;
- else
- {
- if (vol->inDriveQ == false)
- {
- // Added following two lines. Bug#1607768 & 1630408.
- vol->vRefNum = NextQDrive(); // assign a logical drive number
- AddDrive(gDrvrRefNum, vol->vRefNum, &vol->driveStatus.drvQEl);
- vol->inDriveQ = true;
- }
- }
-
- if (PostEvent(diskEvt, vol->vRefNum) == noErr) // Post event for system to mount
- vol->partmounted = true;
- }
- break;
- #endif
-
- case kMediaPowerCSCode: // Set Power Mode
- {
- err = controlErr;
- }
- break;
-
- // Drive Queue support control calls
- case kcsSetDriverMode: // Set Driver Mode
- case kcsManageReadOnlyMediaQueue:
- {
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.theIOPB = nil;
- gTheDriverGlobals.drivePB.ioCommandID = ioCommandID;
-
- // There are no mounted volumes, it is safe to change driver modes
- err = DriveQueueControlCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, &StandardControlCallCompletion );
- }
- break;
-
- // These are the floppy only control calls
- case kSetTagBuffer: // This is a floppy specific control call
- case kTrackCache: // This is a floppy specific control call
- case kDiskCopy: // Floppy specific call to support the DiskCopy Format and Write Image function
- {
- if( IsDriveAFloppy( driveNum ) == true )
- {
- err = FloppyControlCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, &StandardControlCallCompletion );
- }
- else
- {
- err = controlErr; // If not a floppy, this call is not supported.
- }
- }
- break;
-
- // This is where the CD/DVD specific control calls should go
-
- // All PC Exchange specific control calls
- case kRegisterPartition: // Register New Partition
- case kGetADrive: // Get A Drive (Create New Partition)
- case kProhibitMounting:
- {
- err = PCExchangeControlCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, &StandardControlCallCompletion );
- }
- break;
-
- // If it hasn't been handle, maybe it is a Device Access Module specific control call.
- default:
- {
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.theIOPB = nil;
- gTheDriverGlobals.drivePB.ioCommandID = ioCommandID;
- err = HandleControlRequest((UInt32) &gTheDriverGlobals.drivePB, pbPtr, &InitializeDriveAccessDone);
- if (err != kRequestPending )
- {
- gTheDriverGlobals.drivePB.theIOPB = nil;
- gTheDriverGlobals.drivePB.ioCommandID = 0;
- }
- }
- break;
- }
-
- return err;
- }
-
- void StandardControlCallCompletion(UInt32 userData, OSStatus status )
- {
- OSStatus err = status;
- DriveRequestPB *ourPB;
-
- ourPB = ((DriveRequestPB *) userData);
-
- // Signal completion of the command to the operating system
- ourPB->theIOPB = nil;
- FinishCommandProcessing(ourPB->ioCommandID, err);
- }
-
- void InitializeDriveAccessDone(UInt32 userData, OSStatus status )
- {
- OSStatus err = status;
- DriveRequestPB *ourPB;
-
- ourPB = ((DriveRequestPB *) userData);
-
- if( err == noErr )
- {
- err = InstallDriveQueueElement( gTheDriverGlobals.drvrRefNum );
-
- if (err == noErr)
- {
- // See if we can mount the media
- err = MountSecondaryInterrupt(nil,nil);
- //err = SetMountInterruptTimer();
- }
- else
- {
- err = kClassNotConfiguredError;
- }
- }
-
- // Signal completion of the command to the operating system
- ourPB->theIOPB = nil;
- FinishCommandProcessing( ourPB->ioCommandID, err);
- }
-
- // May run at interrupt level, CANNOT allocate or move memory.
- OSStatus DriverStatusCmd ( IOCommandID ioCommandID, ParmBlkPtr pb)
- {
- #pragma unused ( ioCommandID )
-
- OSStatus err = noErr;
- CntrlParamPtr pbPtr;
- SInt16 driveNum;
-
- // Cast the pb pointer to a CntrlParamPtr for easier access to the fields
- pbPtr = (CntrlParamPtr) pb;
- driveNum = pbPtr->ioVRefNum;
-
- // Handle the status call
- switch(pbPtr->csCode)
- {
- case kDriveStatus:
- {
- if ( IsDriveNumberValid( driveNum ) == false )
- {
- err = nsDrvErr; // requested drive doesn't belong to this driver
- }
- else
- {
- GetDriveStatusForDriveNum( driveNum, (DrvSts *) &pbPtr->csParam[0]);
- }
- }
- break;
-
- case kDriverGestaltCode:
- {
- DriverGestaltParam *gestaltPtr; // local pointer to driver gestalt structure
-
- gestaltPtr = (DriverGestaltParam *) pbPtr;
- switch(gestaltPtr->driverGestaltSelector)
- {
- case kdgVersion:
- {
- // Return information on the driver version
- // Get this from the DAM because the driver version may be
- // different for each attachment interface.
- NumVersion* numVersion;
-
- numVersion = GetDriverGestaltVersionResponse(gestaltPtr);
- GetDriverVersionNumber( numVersion );
- }
- break;
-
- case kdgSupportedMediaTypes:
- {
- // Let this be processed by the DAM since it has knowledge
- // of all possible media types for this device.
- DriverGestaltSupportedMediaTypesResponse** supptMediaResponse = GetDriverGestaltSupportedMediaTypesResponse (gestaltPtr);
-
- *supptMediaResponse = GetSupportedMediaTypesPtr();
- }
- break;
-
- case kdgDeviceType:
- {
- // Return the type of media for this drive number.
- DriverGestaltDevTResponse* deviceTypeResponse = GetDriverGestaltDevTResponse(gestaltPtr);
-
- if( IsDriveNumberValid( driveNum ) == true )
- {
- deviceTypeResponse->deviceType = GetMediaTypeForDriveNum( driveNum );
- }
- else
- {
- // requested drive doesn't belong to this driver
- err = nsDrvErr;
- }
- }
- break;
-
- case kdgInterface:
- {
- // Return the interface of the drive in ioVRefNum.
- DriverGestaltIntfResponse* interfaceResponse = GetDriverGestaltIntfResponse(gestaltPtr);
-
- interfaceResponse->interfaceType = GetDriverGestaltIntfForInterface() ;
- }
- break;
-
- case kdgSync:
- {
- // Return true if the driver supports only synchronous behavior
- // Since the native drivers will always be able to handle any type of call,
- // this will always return false.
- DriverGestaltSyncResponse* syncResponse = GetDriverGestaltSyncResponse(gestaltPtr);
-
- syncResponse->behavesSynchronously = false;
- }
- break;
-
- case kdgBoot:
- {
- // Return the ID of the boot device for PRAM storage
- // Since NewWorld Native drivers will have a new DriverGestalt for
- // returning the boot device path, this should never be required to
- // be supported by 'ndrv's.
- err = statusErr;
- }
- break;
-
- case kdgWide:
- {
- // Return whether driver supports large volume addressing (> 4GByte)
- // Since the UnitTable Read/Write handles this automatically, all
- // Fusion drivers support large volume or wide addressing.
- *(GetDriverGestaltBooleanResponse(gestaltPtr)) = true;
- }
- break;
-
- case kdgPurge: // Return if we can be closed and purged from memory.
- {
- DriverGestaltPurgeResponse* response = GetDriverGestaltPurgeResponse(gestaltPtr);
-
- // This will be handled by the appropriate expert.
- // All 'ndrv's should correctly handle a close request, and once closed
- // and finalized, be removed by the appropriate Expert/Loader/Manager
- response->purgePermission = kmNoCloseNoPurge;
- response->purgeDriverPointer = (Ptr) nil;
- }
- break;
-
- case kdgSupportsSwitching:
- {
- // Return whether driver supports low power control call (csCode = 70h)
- *(GetDriverGestaltBooleanResponse(gestaltPtr)) = false;
- }
- break;
-
- case kdgSupportsPowerCtl:
- {
- // Return whether driver supports low power control call (csCode = 70h)
- *(GetDriverGestaltBooleanResponse(gestaltPtr)) = false;
- }
- break;
-
- case kdgAPI:
- {
- // Return whether driver supports PC-Exchange Control and Status calls
- // related to partitioning.
- DriverGestaltAPIResponse* apiResponse = GetDriverGestaltAPIResponse(gestaltPtr);
-
- apiResponse->partitionCmds = 1;
- }
- break;
-
- case kdgFlush:
- {
- // Return whether driver supports the Cache flush Control call,
- // and whether the finder should tell us to flush our cache
- DriverGestaltFlushResponse* response = GetDriverGestaltFlushResponse(gestaltPtr);
-
- response->canFlush = true;
- if( AreThereMountedDrives() == false )
- {
- response->needsFlush = false; // Don't need a flush call because there is no media
- }
- else
- {
- response->needsFlush = true; // Needs a flush call because media is present
- }
- response->canFlush = false;
- response->needsFlush = false;
- }
- break;
-
- case kdgEject:
- {
- // Return whether driver wants eject call for shutdown and restart
- // Eject on restart or shutdown
- DriverGestaltEjectResponse* response = GetDriverGestaltEjectResponse(gestaltPtr);
-
- response->ejectFeatures = 0L; // Clear both Dont Eject Bits, kShutDownDontEject and kRestartDontEject.
- }
- break;
-
- case kdgVMOptions:
- {
- // Return whether drive can be used for Virtual Memory.
- // Determine the return value by whether the interface can
- // support VM and whether the media type is suitable for VM.
- DriverGestaltVMOptionsResponse* response = GetDriverGestaltVMOptionsResponse(gestaltPtr);
-
- // Since this is a per drive call and not a per driver call
- // make sure that the information for a valid drive is being requested.
- if( IsDriveNumberValid( driveNum ) == false )
- {
- // requested drive doesn't belong to this driver
- err = nsDrvErr;
- }
- else
- {
- if (( DoesInterfaceHaveVirtualMemoryCapabilities() == false ) || (IsDriveAFloppy( driveNum ) == true))
- {
- // The current interface does not support VM page mapping, or
- // the media is floppy disk media and we do not want to put
- // this into the VM Page path.
- // Let the system know by returning the Allow None value.
- response->vmOptions = kAllowVMNoneMask;
- }
- else
- {
- if ( IsDriveNumWriteProtected(driveNum) == true )
- {
- // The disk is write protect, let the system know that
- // this drive can only be mapped for reading.
- response->vmOptions = kAllowVMReadOnlyMask;
- }
- else
- {
- // The disk can be used for both reading and writing.
- response->vmOptions = kAllowVMReadWriteMask;
- }
- }
- }
- }
- break;
-
- case kdgMediaInfo:
- {
- // Return back specific information about our media
- // This is a driver level call and does not require that
- // a drive queue number is specified.
- DriverGestaltMediaInfoResponse* response = GetDriverGestaltMediaInfoResponse(gestaltPtr);
- UInt32 currentCapacity, currentBlockSize;
- Boolean isWriteProtected;
- OSType currentMedia;
-
- GetMediaProperties( ¤tCapacity, ¤tBlockSize, &isWriteProtected, ¤tMedia);
-
- response->numberBlocks = currentCapacity;
- response->blockSize = currentBlockSize;
- if ( currentCapacity == 0 )
- {
- // If the capacity is 0, media is not in the drive.
- response->mediaType = kMediaTypeNoMedia;
- }
- else
- {
- response->mediaType = kMediaTypeUnknown;
- }
- }
- break;
-
- /* Return a pointer to a IconFamily ('icns') data structure for */
- /* Disk Driver physical drive (formerly in csCode 22) in driverGestaltResponse. */
- case kdgPhysDriveIconSuite:
-
- /* Return a pointer to a IconFamily ('icns') data structure for */
- /* Disk Driver media (formerly in csCode 21) in driverGestaltResponse. */
- case kdgMediaIconSuite:
- {
- // Check to see if this is a drive that own
- if( IsDriveNumberValid( driveNum ) == true )
- {
- IconFamilyPtr theMediaFamilyPtr = nil;
-
- if( IsDriveAFloppy( driveNum ) == true )
- {
- theMediaFamilyPtr = GetFloppyIconFamilyPtr();
- }
- else
- {
- theMediaFamilyPtr = GetMediaIconFamilyPtr();
- }
-
- if ( theMediaFamilyPtr != nil )
- {
- // We were able to get the Icon Family ptr, return it in the GestaltParam Struct
- gestaltPtr->driverGestaltResponse = (UInt32) theMediaFamilyPtr;
- }
- else
- {
- // We were not able to get the Icon Family pointer, return a status error and
- // let the system use the default icons.
- err = statusErr;
- }
- }
- else
- {
- err = nsDrvErr; // requested drive doesn't belong to this driver
- }
- }
- break;
-
- case kdgMediaName:
- {
- /* Return a pointer to a pascal string describing the Disk Driver (formerly in csCode 21) in driverGestaltResponse. */
- gestaltPtr->driverGestaltResponse = (UInt32) GetDeviceWhereString();
- }
- break;
-
- case kdgDeviceReference:
- {
- GetDriverGestaltDeviceReferenceResponse(gestaltPtr)->devRef = GetDeviceReferenceNumber();
- }
- break;
-
- case kdgNameRegistryEntry:
- {
- GetDriverGestaltNameRegistryResponse(gestaltPtr)->entryID = &gTheDriverGlobals.drvrRegEntryID;
- }
- break;
-
- case kdgDeviceModelInfo:
- {
- *(GetDriverGestaltDeviceModelInfoResponse(gestaltPtr)) = GetDeviceInfoPtr();
- }
- break;
-
- case kdgOpenFirmwareBootSupport:
- case kdgOpenFirmwareBootingSupport:
- {
- DriveQRecPtr theDriveRec;
-
- theDriveRec = FindDriveQRecForDriveNum( driveNum );
-
- if (theDriveRec == nil)
- {
- // Invalid drive number, return an error
- err = nsDrvErr;
- }
- else
- {
- if ( theDriveRec->partMapEntryNum == 0 )
- {
- // If the PMap entry number is zero, the media is not paritioned
- (GetDriverGestaltOFBootSupportResponse(gestaltPtr))->bootPartitionQualifier = kOFBootNotPartitioned;
- }
- else
- {
- (GetDriverGestaltOFBootSupportResponse(gestaltPtr))->bootPartitionQualifier = kOFBootSpecifiedPartition;
- (GetDriverGestaltOFBootSupportResponse(gestaltPtr))->bootPartitionMapEntry = theDriveRec->partMapEntryNum;
- }
- }
- }
- break;
-
- case kdgDriverUtilitySupport:
- {
- *(GetDriverGestaltBooleanResponse(gestaltPtr)) = true;
- }
- break;
-
- default:
- {
- // This call was not handled here, pass to the DAM to see if it knows what to do.
- err = HandleStatusRequest((UInt32) nil, pbPtr, nil);
- }
- }
- }
- break;
-
- case kcsGetBootPartitionStatus: // Is this the boot partition?
- {
- // Return 1 if this drive is the startup partition,
- // else return 0
- pbPtr->csParam[0] = 1;
- err = noErr;
- }
- break;
-
- case kMediaPowerCSCode:
- {
- // Return the current power mode of the drive. NOTE: The power modes (kMediaModeOn,
- // kMediaModeStandBy, kMediaModeSuspend, and kMediaModeOff) are not the same as the ATA modes.
- // The primary difference is kMediaModeSuspend = Standby and kMediaModeStandBy = Idle
- if( AreThereMountedDrives() == false )
- {
- err = nsDrvErr; // no Media is inserted, return an error
- break;
- }
- else
- {
- UInt8 powerMode = kMediaModeOn; // Always report that the drive is active
-
- // Return the power mode in the upper byte of csParam[0], lower byte is cleared
- pbPtr->csParam[0] = powerMode << 8;
- }
- }
- break;
-
- // Drive Queue support status calls
- case kcsGetDriverMode: // Get Driver Mode
- case kcsManageReadOnlyMediaQueue:
- {
- err = DriveQueueStatusCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, nil );
- }
- break;
-
- // All Floppy disk specific status calls
- case kReturnFormatList:
- case kMFMStatus:
- case kDuplicatorVersion: // DiskCopy version supported
- {
- if( IsDriveAFloppy( driveNum ) == true )
- {
- err = FloppyStatusCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, nil );
- }
- else
- {
- err = statusErr;
- }
- }
- break;
-
- // All PC Exchange specific status calls
- case kGetPartitionStatus:
- case kGetPartInfo:
- {
- err = PCExchangeStatusCallSupport( (UInt32) &gTheDriverGlobals.drivePB, pbPtr, nil );
- }
- break;
-
- // Unrecognized status call, should add call to the DAM's status routine.
- default:
- {
- err = statusErr;
- }
- break;
- }
-
- return(err);
- }
-
- // May run at interrupt level, CANNOT allocate or move memory.
- OSStatus DriverReadCmd ( IOCommandID ioCommandID,
- ParmBlkPtr pb)
- {
- OSStatus err = ioErr;
-
- if( AreThereMountedDrives() == false )
- {
- err = ioErr;
- }
- else
- {
- // Clear out the Drive request PB
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.theIOPB = pb;
- gTheDriverGlobals.drivePB.ioCommandID = ioCommandID;
-
- err = DoReadWriteCommand( (UInt32) &gTheDriverGlobals.drivePB, (IOParamPtr) pb, ((IOParamPtr) pb)->ioVRefNum, false, &ReadWriteFinishCommand );
- if ( err != kRequestPending )
- {
- // The request is not pending, This means that it is either done, or an error
- // occurred. Either way, we need to clear out the Drive request PB.
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
- }
- }
-
- return(err);
- }
-
- // May run at interrupt level, CANNOT allocate or move memory.
- OSStatus DriverWriteCmd ( IOCommandID ioCommandID,
- ParmBlkPtr pb)
- {
- OSStatus err = ioErr;
-
- if( AreThereMountedDrives() == false )
- {
- err = ioErr;
- }
- else
- {
- // Clear out the Drive request PB
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.theIOPB = pb;
- gTheDriverGlobals.drivePB.ioCommandID = ioCommandID;
-
- err = DoReadWriteCommand( (UInt32) &gTheDriverGlobals.drivePB, (IOParamPtr) pb, ((IOParamPtr) pb)->ioVRefNum, true, &ReadWriteFinishCommand );
- if ( err != kRequestPending )
- {
- // The request is not pending, This means that it is either done, or an error
- // occurred. Either way, we need to clear out the Drive request PB.
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
- }
- }
-
- return(err);
- }
-
- void ReadWriteFinishCommand ( UInt32 userData, OSStatus status )
- {
- DriveRequestPBPtr ourPB;
- IOParamPtr iopb;
-
- ourPB = (DriveRequestPBPtr) userData;
- iopb = (IOParamPtr) ourPB->theIOPB;
-
- if ( status == noErr )
- {
- // All data was transferred, update actCount field
- iopb->ioActCount = iopb->ioReqCount;
- }
- else
- {
- // An error occurred, make sure actCount is zeroed
- iopb->ioActCount = 0;
- }
-
- ourPB->theIOPB = nil;
- FinishCommandProcessing(ourPB->ioCommandID, status);
- }
-
-
- // May run at interrupt level, CANNOT allocate or move memory.
- OSStatus DriverKillIOCmd (ParmBlkPtr pb)
- {
- #pragma unused (pb)
- OSStatus err = noErr;
-
- return err;
- }
-
- #pragma mark -
- #pragma mark Media Mounting Routines
- // **************************************************************************
- // All Mount Timer interrupt routines
- // **************************************************************************
- OSStatus SetMountInterruptTimer( void )
- {
- OSStatus status;
- AbsoluteTime theWait;
-
- // If there is an outstanding timer, cancel it
- ClearMountInterruptTimer();
-
- theWait = DurationToAbsolute(durationSecond);
- theWait = AddAbsoluteToAbsolute(UpTime(), theWait);
- status = SetInterruptTimer( &theWait, &MountSecondaryInterrupt, nil, &gInterruptTimer);
-
- return status;
- }
-
- OSStatus ClearMountInterruptTimer( void )
- {
- OSStatus status = noErr;
-
- if( gInterruptTimer != nil )
- {
- AbsoluteTime timeLeft;
-
- // Cancel any pending timers
- status = CancelTimer( gInterruptTimer, &timeLeft);
- gInterruptTimer = 0;
- }
-
- return status;
- }
-
-
- OSStatus MountSecondaryInterrupt( void *p1, void *p2)
- {
- #pragma unused ( p1, p2 )
- OSStatus status;
-
- gInterruptTimer = 0;
-
- if( IsDeviceAccessEnabled() == false )
- {
- status = SetMountInterruptTimer();
- }
- else
- {
- gTheDriverGlobals.drivePB.currentExecutionState = kMountStartState;
- MountTheCartridge( (UInt32) &gTheDriverGlobals.drivePB, noErr );
- }
-
- return noErr;
- }
-
-
- // **************************************************************************
- // Mount State Machine and associated completion routines
- // **************************************************************************
- void MountTheCartridge( UInt32 userData, OSStatus status )
- {
- OSStatus err = status;
- DriveRequestPB *ourPB;
-
- ourPB = (DriveRequestPB *) userData;
-
- switch (ourPB->currentExecutionState )
- {
- case kMountStartState:
- {
- ourPB->currentExecutionState = kMountPreventRemovalState;
- err = CheckIfMediaIsPresent( (UInt32) ourPB,
- (CheckIfMediaIsPresentCompletionProcPtr) MountTheCartridge );
- }
- break;
-
- case kMountPreventRemovalState:
- {
- if( status == noErr )
- {
- // Media was detected, lock it in place.
- ourPB->currentExecutionState = kMountInstallDriveState;
- err = PreventMediaRemoval ((UInt32) ourPB, MountTheCartridge );
- }
- else
- {
- err = status;
- }
- }
- break;
-
- case kMountInstallDriveState:
- {
- // The device is now mounted, and the Media is locked in place.
- // There is nothing left for us to do, so just break.
- InstallDrive( DriveInstallCompletion );
- err = kRequestPending;
- }
- break;
- }
-
- if (( err != kRequestPending ) && ( err != noErr ))
- {
- if ( err == kDeviceAccessMediaUnusable )
- {
- // We can not use this cartridge, go ahead and eject it
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.currentExecutionState = kEjectStartState;
- EjectTheCartridge( (UInt32)&gTheDriverGlobals, noErr );
- }
- else
- {
- // Reset the interrupt and try again
- ourPB->currentExecutionState = kMountStartState;
- err = SetMountInterruptTimer();
- }
- }
- }
-
- void DriveInstallCompletion(Boolean wasSuccessful)
- {
- if((wasSuccessful == false ) || (GetNumberOfVolumes() == 0))
- {
- BlockZero((Ptr) &gTheDriverGlobals.drivePB, sizeof(DriveRequestPB));
-
- gTheDriverGlobals.drivePB.currentExecutionState = kEjectStartState;
- EjectTheCartridge( (UInt32)&gTheDriverGlobals, noErr );
- }
- }
-
-
- #pragma mark -
- #pragma mark Media Ejecting Routines
- // **************************************************************************
- // Eject State Machine and associated completion routines
- // **************************************************************************
- void EjectTheCartridge( UInt32 theCurrentPB, OSStatus status )
- {
- OSStatus err = noErr;
- DriveRequestPB *ourPB = (DriveRequestPB *) theCurrentPB;
-
- switch (ourPB->currentExecutionState )
- {
- case kEjectStartState:
- {
- ourPB->currentExecutionState = kEjectAllowRemovalDone;
- err = AllowMediaRemoval ( (UInt32)ourPB, EjectTheCartridge ); // Allow for Ejects
- if ( err != noErr )
- {
- // Either an error occurred, or the request is pending.
- // In either case, break out of the switch statement
- // and let the code outside the switch decide what to do.
- break;
- }
-
- // If an immediate noErr occurred from UnlockMedia,
- // it means that the media is not locked in the drive.
- // The drive is probably a manual eject drive.
- // In any case, fall through to the kEjectAllowRemovalDone
- // state and continue execution.
- }
- /* -- break intentionally left out -- */
-
- case kEjectAllowRemovalDone:
- {
- ourPB->currentExecutionState = kEjectCartridgeDone;
- err = EjectCartridge ( (UInt32)ourPB, EjectTheCartridge ); // Now eject the cartridge
-
- if( err == noErr )
- {
- ourPB->currentExecutionState = kMountStartState; // reset the machine
- SetMountInterruptTimer();
- }
- }
- break;
-
- case kEjectCartridgeDone:
- {
- err = noErr;
- if( status == noErr )
- {
- ourPB->currentExecutionState = kMountStartState; // reset the machine
- SetMountInterruptTimer();
- }
- }
- break;
- }
-
- if ( err != kRequestPending )
- {
- if ( ourPB->theIOPB != nil )
- {
- // Signal completion of the command to the operating system
- ourPB->theIOPB = nil;
- FinishCommandProcessing(ourPB->ioCommandID, noErr);
- }
- }
- }
-
-
-